﻿#include "coroutines/Delay.h"
#include <chrono>
#include <iostream>

namespace Delay {

#pragma region Awaiter
void Awaiter::await_suspend(std::coroutine_handle<Promise> handle) {
    CachedHandle = handle;
    CachedHandle.promise().SetAwaiter(this);
    ThreadFuture = ThreadPromise.get_future();

    // 启动一个原生 std::thread，并将 promise 的所有权移交给它，异步执行resume比较危险
    std::thread(
        Awaiter::async_delay,
        std::ref(Duration),
        std::ref(ThreadPromise)
    ).detach();
};
void Awaiter::await_resume() noexcept {
    CachedHandle.promise().SetAwaiter(nullptr);
}
bool Awaiter::QueryFinished() {
    if (ThreadFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
        CachedHandle.resume();
        return true;
    }
    return false;
}
#pragma endregion

#pragma region Promise
bool Promise::QueryAwaiterFinished() {
    if (CurrentAwaiter == nullptr) {
        return true;
    }
    return CurrentAwaiter->QueryFinished();
}
#pragma endregion

Coroutine CoroutineFunc() {
    static const double DelayTime = 2.0;
    
    std::cout << "Start Delay: " << DelayTime << "s" << std::endl;
    co_await DelayTime;
    std::cout << "End Delay" << std::endl;
}

void Test() {
    auto CoroutineHandle = CoroutineFunc();
    // 轮询非阻塞
    while (!CoroutineHandle.handle.done()) {
        while (!CoroutineHandle.handle.promise().QueryAwaiterFinished()) {
        }
    }
    std::cout << CoroutineHandle.handle.done() << std::endl;
}

}
